package lockRelate

import (
	"fmt"
	"hash/fnv"
	"sync"
)

/*
	互斥锁（sync.Mutex）
	互斥锁是一种最简单的锁机制，用于保护共享资源，确保同一时间只有一个 goroutine 可以访问资源。
	优点:
		1.简单易用：
			实现简单，适合保护单个共享资源。
		2.通用性强：
			适用于大多数并发场景。
		3.无额外开销：
			不需要额外的数据结构或计算。
	缺点:
		1.锁粒度粗：
			如果锁保护的资源过多，会导致锁竞争激烈，性能下降。
		2.不支持读写分离：
			读写操作都需要加锁，无法实现读操作的并发。
		3.容易死锁：
		如果加锁和解锁的顺序不当，可能导致死锁。
	适用场景：
		1.保护单个共享资源。
		2.并发量较低的场景。
		3.不需要区分读写操作的场景

########################################################################################################################

	哈希锁(HashLock)
	哈希锁是一种细粒度的锁机制，通过将资源映射到多个锁上，减少锁竞争。每个资源对应一个锁，不同资源可以并发访问。
	优点:
		1.细粒度锁：
			不同资源可以并发访问，减少锁竞争。
		2.高性能：
			在高并发场景下，性能优于全局互斥锁。
		3.灵活性强：
			可以根据资源数量动态调整锁的数量。
	缺点:
		1.实现复杂：
			需要设计哈希函数和锁分配逻辑。
		2.哈希冲突：
			不同资源可能映射到同一个锁，导致锁竞争。
		3.内存开销：
			需要维护多个锁，占用更多内存。
	适用场景
	 	1.保护多个共享资源。
		2.高并发场景。
		3.需要细粒度锁控制的场景。

	选择互斥锁的场景
		1.保护单个共享资源。
		2.并发量较低。
		3.实现简单，无需额外开销。

	选择哈希锁的场景
		1.保护多个共享资源。
		2.高并发场景，需要细粒度锁控制。
		3.允许一定的实现复杂度和内存开销。
*/

// HashLock 哈希锁结构
type HashLock struct {
	locks []*sync.Mutex // 一组互斥锁
	count int           // 锁的数量
}

// NewHashLock 创造一个HashLock
func NewHashLock(count int) *HashLock {
	// 创造一个切片确定容量长度
	locks := make([]*sync.Mutex, count)
	for i := 0; i < count; i++ {
		locks[i] = &sync.Mutex{}
	}
	return &HashLock{
		locks: locks,
		count: count,
	}
}

// Lock 根据key加锁
func (h *HashLock) Lock(key string) {
	index := h.hash(key) % uint32(h.count)
	h.locks[index].Lock()
}

// Unlock 根据key解锁
func (h *HashLock) Unlock(key string) {
	index := h.hash(key) % uint32(h.count)
	h.locks[index].Unlock()
}

// hash 计算key的哈希值
func (h *HashLock) hash(key string) uint32 {
	hasher := fnv.New32a()
	_, err := hasher.Write([]byte(key))
	if err != nil {
		fmt.Println(err)
	}
	//fmt.Println("uint32 hashValue => ", hasher.Sum32())
	return hasher.Sum32()
}
